package com.job.meeting.tools;

import com.google.gson.Gson;
import com.job.meeting.pojo.user;
import com.job.meeting.service.userService;
import lombok.Data;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cglib.core.EmitUtils;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.job.meeting.pojo.*;
import org.thymeleaf.expression.Bools;

@Service
public class wechatSystem {
    userService userService = null;

    final private String appID = "wxac1094f5cf5340ef";
    final private String appSecret = "c865a1b038251b451292a144450339f9";

    private long normalAccessTokenTime = -1;
    private normalAccessTokenJson normalAccessToken;

    private long loginAccessTokenTime = -1;
    private loginAccessTokenJson loginAccessToken;

    public enum Privilege {
        NORMAL, ADMINISTRATION
    }

    public wechatSystem(userService us)
    {
        this.userService = us;
    }

    @Data
    private class _User {
        private String openid;
        private String nickname;
        private int sex;
        private String province;
        private String city;
        private String country;
        private String headimgurl;
        private String unionid;
        private String[] privilege;
    }

    @Data//负责处理正常情况下，比如群发消息的access_token
    private class normalAccessTokenJson {
        private String access_token;
        long expires_in;
    }

    @Data//仅负责处理登陆情况下所需的access_token
    public class loginAccessTokenJson {
        private String access_token;
        long expires_in;
        String refresh_token;
        String openid;
        String scope;
    }

    @Data//模板消息的组装
    private class templateMessage<T> {
        private String touser;
        private String template_id;
        private T data;
    }

    //通过openid获得微信用户的信息
    public user getWechatUser(String code) {
        loginAccessTokenJson json = this.getLoginAccessToken(code);
        RestTemplate restTemplate = new RestTemplate();
        restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
        Map<String, String> params = new HashMap<>();
        params.put("access_token", json.getAccess_token());
        params.put("openid", json.getOpenid());
        params.put("lang", "zh_CN");
        ResponseEntity<String> responseEntity = restTemplate.getForEntity(
                "https://api.weixin.qq.com/sns/userinfo?access_token={access_token}&openid={openid}&lang={lang}",
                String.class,
                params);
        String respond = responseEntity.getBody();

        _User user = new Gson().fromJson(respond, _User.class);
        user u = new user();
        u.setCity(user.getCity());
        u.setCountry(user.getCountry());
        u.setHeadimgurl(user.getHeadimgurl());
        u.setNickname(user.getNickname());
        u.setOpenid(user.getOpenid());
        u.setPrivilege(0);
        u.setProvince(user.getProvince());
        u.setSex(user.getSex());
        u.setUnionid(user.getUnionid());
        u.setReal_name("");
        return u;
    }

    //获取access_token。如果没有过期就就不要拿新的了，直接用本来就有的；
    // 否则，获得一个新的access_token。
    private String getNormalAccessToken() {
        if (normalAccessTokenTime == -1 || System.currentTimeMillis() - normalAccessTokenTime > normalAccessToken.getExpires_in()) {
            RestTemplate restTemplate = new RestTemplate();
            Map<String, String> params = new HashMap<>();
            params.put("grant_type", "client_credential");
            params.put("appid", appID);
            params.put("secret", appSecret);
            normalAccessTokenTime = System.currentTimeMillis();
            ResponseEntity<String> responseEntity = restTemplate.getForEntity(
                    "https://api.weixin.qq.com/cgi-bin/token?grant_type={grant_type}&appid={appid}&secret={secret}",
                    String.class,
                    params);
            String respond = responseEntity.getBody();
            normalAccessToken = new Gson().fromJson(respond, normalAccessTokenJson.class);
        }
        return normalAccessToken.getAccess_token();
    }

    //获取登录所需的特别的access_token，分为三种情况：
    //如果从未获取，或者已经过期，那么从零开始获取
    //否则直接返回
    private loginAccessTokenJson getLoginAccessToken(String code) {
        if (loginAccessTokenTime == -1 || System.currentTimeMillis() - loginAccessTokenTime > loginAccessToken.getExpires_in()) {
            RestTemplate restTemplate = new RestTemplate();
            Map<String, String> params = new HashMap<>();
            params.put("grant_type", "authorization_code");
            params.put("code", code);
            params.put("appid", appID);
            params.put("secret", appSecret);
            loginAccessTokenTime = System.currentTimeMillis();
            ResponseEntity<String> responseEntity = restTemplate.getForEntity(
                    "https://api.weixin.qq.com/sns/oauth2/access_token?appid={appid}&secret={secret}&code={code}&grant_type={grant_type}",
                    String.class,
                    params);
            String respond = responseEntity.getBody();
            loginAccessToken = new Gson().fromJson(respond, loginAccessTokenJson.class);
        }
        return loginAccessToken;
    }


    //给定innerData要求的json信息以及需要发送的人群，来群发信息，我建议使用个体发送版本来完成这个函数
    public void sendMessage(wechatMessageNewMeeting message, Privilege privilege) {
        List<user> userList = userService.getUserByPrivileges(privilege.ordinal());
        for (user u : userList) {
            sendMessage(message, u.getOpenid());
        }
    }

    public void sendMessage(wechatMessageMeetingUpdate message, Privilege privilege) {
        List<user> userList = userService.getUserByPrivileges(privilege.ordinal());
        for (user u : userList) {
            sendMessage(message, u.getOpenid());
        }
    }


    //给定innerData要求的json信息以及要发送的用户的openid，给特定人发送信息
    public void sendMessage(wechatMessageMeetingUpdate message, String openID) {
        RestTemplate restTemplate = new RestTemplate();
        restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
        String assembled = assembleMessage(message, openID);
        ResponseEntity<String> responseEntity = restTemplate.postForEntity(
                "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + getNormalAccessToken(),
                assembled,
                String.class);
        System.out.println(responseEntity.getBody());
    }

    public void sendMessage(wechatMessageNewMeeting message, String openID) {
        RestTemplate restTemplate = new RestTemplate();
        restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
        String assembled = assembleMessage(message, openID);
        ResponseEntity<String> responseEntity = restTemplate.postForEntity(
                "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + getNormalAccessToken(),
                assembled,
                String.class);
        System.out.println(responseEntity.getBody());
    }

    //组装文字信息。给定接收方的openID以及消息内容，组装符合微信格式的json消息字段
    private String assembleMessage(wechatMessageMeetingUpdate data, String openID) {
        templateMessage<wechatMessageMeetingUpdate> message = new templateMessage();
        message.setTouser(openID);
        message.setData(data);
        message.setTemplate_id("4JbBuiWwK3oqz_BYktmY2STs6-1NfR8AOcTlADIIk9Y");
        return new Gson().toJson(message);
    }

    private String assembleMessage(wechatMessageNewMeeting data, String openID) {
        templateMessage<wechatMessageNewMeeting> message = new templateMessage();
        message.setTouser(openID);
        message.setData(data);
        message.setTemplate_id("HX79-kX9R44agmPmc6hSB5fUwke77nTuW2wNgcKEIsc");
        return new Gson().toJson(message);
    }
}